package DyingBaby.backend.sql;
/**
 * SQL 解析器
 * 使用词法分析器（Lexer）将 SQL 语句转换为抽象语法树（AST）
 */

import DyingBaby.backend.catalog.ColumnDef;
import DyingBaby.backend.catalog.ColumnType;

import java.util.*;

public class Parser {
    private final List<Lexer.Token> tokens;
    private int i = 0;

    public Parser(String sql) {
        this.tokens = new Lexer(sql).tokenize();
    }

    public static Object parse(String sql) {
        return new Parser(sql).parseStmt();
    }

    /**
     * Token处理的辅助方法
     * @return
     */
    // 返回当前 Token，但不移动指针
    private Lexer.Token peek() { return tokens.get(i); }
    //返回当前 Token 并移动指针到下一个。
    private Lexer.Token next() { return tokens.get(i++); }
    //检查当前 Token 是否与指定的类型和文本匹配。
    private boolean match(Lexer.Type t, String textUp) {
        if (i >= tokens.size()) return false;
        Lexer.Token tk = tokens.get(i);
        if (tk.type != t) return false;
        if (textUp == null) return true;
        return tk.text.equalsIgnoreCase(textUp);
    }
    //期望当前 Token 匹配指定的类型和文本
    private void expect(Lexer.Type t, String textUp) {
        if (!match(t, textUp)) throw new IllegalArgumentException("Expect " + t + " " + (textUp==null?"":textUp) + ", got " + peek());
        i++;
    }


    /**
     * 解析SQL语句
     */
    //根据第一个关键字决定调用哪个具体的解析方法。
    private Object parseStmt() {
        if (match(Lexer.Type.KEYWORD, "CREATE")) return parseCreate();
        if (match(Lexer.Type.KEYWORD, "INSERT")) return parseInsert();
        if (match(Lexer.Type.KEYWORD, "SELECT")) return parseSelect();
        if (match(Lexer.Type.KEYWORD, "UPDATE")) return parseUpdate();
        if (match(Lexer.Type.KEYWORD, "DELETE")) return parseDelete();
        throw new IllegalArgumentException("Unsupported SQL starting at: " + peek());
    }

    //解析 CREATE TABLE 语句，包括表名、列定义和主键信息。
    private Ast.CreateTable parseCreate() {
        expect(Lexer.Type.KEYWORD, "CREATE");
        expect(Lexer.Type.KEYWORD, "TABLE");
        String table = nextIdent();
        expect(Lexer.Type.SYMBOL, "(");
        List<ColumnDef> cols = new ArrayList<>();
        String primary = null;
        while (!match(Lexer.Type.SYMBOL, ")")) {
            if (match(Lexer.Type.KEYWORD, "PRIMARY")) {
                next(); expect(Lexer.Type.KEYWORD, "KEY"); expect(Lexer.Type.SYMBOL, "(");
                primary = nextIdent(); expect(Lexer.Type.SYMBOL, ")");
            } else {
                String col = nextIdent();
                ColumnType type;
                Integer len = null;
                if (match(Lexer.Type.KEYWORD, "INT")) { next(); type = ColumnType.INT; }
                else if (match(Lexer.Type.KEYWORD, "STRING")) {
                    next(); type = ColumnType.STRING;
                    if (match(Lexer.Type.SYMBOL, "(")) {
                        next(); len = Integer.parseInt(next().text); expect(Lexer.Type.SYMBOL, ")");
                    }
                } else throw new IllegalArgumentException("Unsupported type: " + next().text);
                cols.add(new ColumnDef(col, type, len));
            }
            if (match(Lexer.Type.SYMBOL, ",")) next();
        }
        expect(Lexer.Type.SYMBOL, ")");
        return new Ast.CreateTable(table, cols, primary);
    }

    private Ast.Insert parseInsert() {
        expect(Lexer.Type.KEYWORD, "INSERT");
        expect(Lexer.Type.KEYWORD, "INTO");
        String table = nextIdent();
        expect(Lexer.Type.SYMBOL, "(");
        List<String> cols = new ArrayList<>();
        while (!match(Lexer.Type.SYMBOL, ")")) {
            cols.add(nextIdent());
            if (match(Lexer.Type.SYMBOL, ",")) next();
        }
        expect(Lexer.Type.SYMBOL, ")");
        expect(Lexer.Type.KEYWORD, "VALUES");
        expect(Lexer.Type.SYMBOL, "(");
        List<Object> vals = new ArrayList<>();
        while (!match(Lexer.Type.SYMBOL, ")")) {
            vals.add(nextValue());
            if (match(Lexer.Type.SYMBOL, ",")) next();
        }
        expect(Lexer.Type.SYMBOL, ")");
        if (cols.size() != vals.size()) throw new IllegalArgumentException("Columns and values size mismatch");
        Map<String,Object> map = new LinkedHashMap<>();
        for (int k=0;k<cols.size();k++) map.put(cols.get(k), vals.get(k));
        return new Ast.Insert(table, map);
    }

    private Ast.Select parseSelect() {
        expect(Lexer.Type.KEYWORD, "SELECT");
        // '*' or specific columns are ignored for now; project all
        while (!match(Lexer.Type.KEYWORD, "FROM")) next();
        expect(Lexer.Type.KEYWORD, "FROM");
        String table = nextIdent();
        Ast.Expr pred = null;
        if (match(Lexer.Type.KEYWORD, "WHERE")) {
            next(); pred = parsePredicate();
        }
        return new Ast.Select(table, pred);
    }

    private Ast.Update parseUpdate() {
        expect(Lexer.Type.KEYWORD, "UPDATE");
        String table = nextIdent();
        expect(Lexer.Type.KEYWORD, "SET");
        Map<String,Object> set = new LinkedHashMap<>();
        do {
            String col = nextIdent();
            expect(Lexer.Type.SYMBOL, "=");
            Object v = nextValue();
            set.put(col, v);
        } while (match(Lexer.Type.SYMBOL, ",") && next()!=null);
        Ast.Expr pred = null;
        if (match(Lexer.Type.KEYWORD, "WHERE")) { next(); pred = parsePredicate(); }
        return new Ast.Update(table, set, pred);
    }

    private Ast.Delete parseDelete() {
        expect(Lexer.Type.KEYWORD, "DELETE");
        expect(Lexer.Type.KEYWORD, "FROM");
        String table = nextIdent();
        Ast.Expr pred = null;
        if (match(Lexer.Type.KEYWORD, "WHERE")) { next(); pred = parsePredicate(); }
        return new Ast.Delete(table, pred);
    }

    /**
     * 辅助解析方法
     */
    //解析 WHERE 子句中的条件表达式
    private Ast.Expr parsePredicate() {
        return parseOr();
    }

    // 解析 OR 表达式 (优先级最低)
    private Ast.Expr parseOr() {
        Ast.Expr left = parseAnd();
        while (match(Lexer.Type.KEYWORD, "OR")) {
            next();
            Ast.Expr right = parseAnd();
            left = new Ast.Or(left, right);
        }
        return left;
    }

    // 解析 AND 表达式
    private Ast.Expr parseAnd() {
        Ast.Expr left = parseNot();
        while (match(Lexer.Type.KEYWORD, "AND")) {
            next();
            Ast.Expr right = parseNot();
            left = new Ast.And(left, right);
        }
        return left;
    }

    // 解析 NOT 表达式
    private Ast.Expr parseNot() {
        if (match(Lexer.Type.KEYWORD, "NOT")) {
            next();
            // NOT 后面可以是任何表达式，包括括号表达式
            if (match(Lexer.Type.SYMBOL, "(")) {
                next();
                Ast.Expr expr = parseOr();
                expect(Lexer.Type.SYMBOL, ")");
                return new Ast.Not(new Ast.Paren(expr));
            } else {
                return new Ast.Not(parseComparison());
            }
        }
        return parseComparison();
    }

    // 解析比较表达式
    private Ast.Expr parseComparison() {
        // 处理括号表达式
        if (match(Lexer.Type.SYMBOL, "(")) {
            next();
            Ast.Expr expr = parseOr();
            expect(Lexer.Type.SYMBOL, ")");
            return new Ast.Paren(expr);
        }

        String col = nextIdent();
        Lexer.Token op = next();

        switch (op.type) {
            case SYMBOL:
                switch (op.text) {
                    case "=":
                        return new Ast.Eq(col, nextValue());
                    case "!=":
                    case "<>":
                        return new Ast.Ne(col, nextValue());
                    case ">":
                        return new Ast.Gt(col, nextValue());
                    case "<":
                        return new Ast.Lt(col, nextValue());
                    case ">=":
                        return new Ast.Ge(col, nextValue());
                    case "<=":
                        return new Ast.Le(col, nextValue());
                    default:
                        throw new IllegalArgumentException("Unsupported operator: " + op.text);
                }
            default:
                throw new IllegalArgumentException("Expected comparison operator, got: " + op);
        }
    }

    //获取下一个标识符
    private String nextIdent() {
        Lexer.Token t = next();
        if (t.type == Lexer.Type.IDENT || t.type == Lexer.Type.KEYWORD) return t.text;
        throw new IllegalArgumentException("Expect identifier, got: " + t);
    }

    //获取下一个值
    private Object nextValue() {
        Lexer.Token t = next();
        switch (t.type) {
            case STRING: return t.text;
            case NUMBER: return Integer.parseInt(t.text);
            case IDENT: return t.text; // fallback
            default: throw new IllegalArgumentException("Expect value, got: " + t);
        }
    }
} 